package com.yuelao.yuelao_backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuelao.yuelao_backend.common.BizException;
import com.yuelao.yuelao_backend.common.ErrorCode;
import com.yuelao.yuelao_backend.dto.TaskDTO;
import com.yuelao.yuelao_backend.entity.Task;
import com.yuelao.yuelao_backend.entity.User;
import com.yuelao.yuelao_backend.entity.UserTask;
import com.yuelao.yuelao_backend.mapper.TaskMapper;
import com.yuelao.yuelao_backend.mapper.UserMapper;
import com.yuelao.yuelao_backend.mapper.UserTaskMapper;
import com.yuelao.yuelao_backend.service.AchievementService;
import com.yuelao.yuelao_backend.service.CoinService;
import com.yuelao.yuelao_backend.service.TaskService;
import com.yuelao.yuelao_backend.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {

    @Resource
    private TaskMapper taskMapper;
    
    @Resource
    private UserMapper userMapper;

    @Resource
    private UserTaskMapper userTaskMapper;

    @Resource
    private UserService userService;

    @Resource
    private CoinService coinService;

    @Resource
    private AchievementService achievementService;


    @Override
    public List<TaskDTO> getDailyTasks(Long userId) {
        LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Task::getType, "daily")
                .eq(Task::getStatus, 1)
                .orderByAsc(Task::getSortOrder);
        List<Task> dailyTasks = list(queryWrapper);

        return dailyTasks.stream()
                .map(task -> convertToTaskDTO(task, userId))
                .collect(Collectors.toList());
    }

    @Override
    public Map<String, Object> getCheckinInfo(Long userId) {
        Map<String, Object> result = new HashMap<>();
        LocalDate today = LocalDate.now();

        // 查找签到任务配置
        LambdaQueryWrapper<Task> taskQuery = new LambdaQueryWrapper<>();
        taskQuery.eq(Task::getTaskKey, "daily_checkin")
                .eq(Task::getStatus, 1);
        Task checkinTask = getOne(taskQuery);
        
        if (checkinTask == null) {
            result.put("today_checked", false);
            result.put("consecutive_days", 0);
            result.put("total_days", 0);
            result.put("today_reward", 0);
            result.put("weekly_bonus", 0);
            result.put("checkin_calendar", new ArrayList<>());
            return result;
        }

        // 查询今日签到记录
        LambdaQueryWrapper<UserTask> checkinQuery = new LambdaQueryWrapper<>();
        checkinQuery.eq(UserTask::getUserId, userId)
                .eq(UserTask::getTaskId, checkinTask.getId())
                .eq(UserTask::getDate, today);
        UserTask todayCheckin = userTaskMapper.selectOne(checkinQuery);

        // 计算连续签到天数
        int continuousCheckinDays = 0;
        LocalDate tempDate = today;
        while (true) {
            LocalDate finalTempDate = tempDate;
            LambdaQueryWrapper<UserTask> continuousQuery = new LambdaQueryWrapper<>();
            continuousQuery.eq(UserTask::getUserId, userId)
                    .eq(UserTask::getTaskId, checkinTask.getId())
                    .eq(UserTask::getDate, finalTempDate);
            UserTask checkinRecord = userTaskMapper.selectOne(continuousQuery);

            if (checkinRecord != null && checkinRecord.getIsCompleted()) {
                continuousCheckinDays++;
                tempDate = tempDate.minusDays(1);
            } else {
                break;
            }
        }

        // 计算总签到天数
        LambdaQueryWrapper<UserTask> totalQuery = new LambdaQueryWrapper<>();
        totalQuery.eq(UserTask::getUserId, userId)
                .eq(UserTask::getTaskId, checkinTask.getId())
                .eq(UserTask::getIsCompleted, true);
        Long totalCheckinDays = userTaskMapper.selectCount(totalQuery);

        // 计算今日奖励（基础奖励 + 连续签到奖励）
        int todayReward = checkinTask.getReward();
        int weeklyBonus = 0;
        if (continuousCheckinDays >= 7) {
            weeklyBonus = todayReward * 2; // 连续7天奖励为基础奖励的2倍
        }

        // 生成签到日历（当月整月）
        List<Map<String, Object>> checkinCalendar = new ArrayList<>();
        LocalDate firstDayOfMonth = today.withDayOfMonth(1);
        LocalDate lastDayOfMonth = today.withDayOfMonth(today.lengthOfMonth());
        
        // 获取当月天数
        int daysInMonth = today.lengthOfMonth();
        
        for (int day = 1; day <= daysInMonth; day++) {
            LocalDate currentDate = firstDayOfMonth.withDayOfMonth(day);
            Map<String, Object> dayInfo = new HashMap<>();
            dayInfo.put("date", currentDate.toString());
            dayInfo.put("day", day); // 添加日期数字
            dayInfo.put("is_today", currentDate.equals(today)); // 是否为今天
            dayInfo.put("checked", false);
            
            LambdaQueryWrapper<UserTask> dayQuery = new LambdaQueryWrapper<>();
            dayQuery.eq(UserTask::getUserId, userId)
                    .eq(UserTask::getTaskId, checkinTask.getId())
                    .eq(UserTask::getDate, currentDate)
                    .eq(UserTask::getIsCompleted, true);
            UserTask dayRecord = userTaskMapper.selectOne(dayQuery);
            
            if (dayRecord != null) {
                dayInfo.put("checked", true);
                dayInfo.put("reward", dayRecord.getTarget()); // 使用target存储当日奖励
            }
            
            // 如果是未来的日期，标记为不可签到
            if (currentDate.isAfter(today)) {
                dayInfo.put("checkable", false);
            } else {
                dayInfo.put("checkable", true);
            }
            
            checkinCalendar.add(dayInfo);
        }

        // 组装返回结果
        result.put("today_checked", todayCheckin != null && todayCheckin.getIsCompleted());
        result.put("consecutive_days", continuousCheckinDays);
        result.put("total_days", totalCheckinDays.intValue());
        result.put("today_reward", todayReward + weeklyBonus);
        result.put("weekly_bonus", weeklyBonus);
        result.put("checkin_calendar", checkinCalendar);
        
        // 添加月份信息
        result.put("current_year", today.getYear());
        result.put("current_month", today.getMonthValue());
        result.put("month_name", today.getMonth().toString());
        result.put("days_in_month", today.lengthOfMonth());
        
        return result;
    }

    @Override
    @Transactional
    public Map<String, Object> doCheckin(Long userId) {
        Map<String, Object> checkinInfo = getCheckinInfo(userId);
        Boolean todayChecked = (Boolean) checkinInfo.get("today_checked");
        if (todayChecked) {
            throw new BizException(ErrorCode.OPERATION_ERROR, "今日已签到，请勿重复签到");
        }

        // 查找签到任务配置
        LambdaQueryWrapper<Task> taskQuery = new LambdaQueryWrapper<>();
        taskQuery.eq(Task::getTaskKey, "daily_checkin")
                .eq(Task::getStatus, 1);
        Task checkinTask = getOne(taskQuery);
        
        if (checkinTask == null || !"daily".equals(checkinTask.getType())) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "签到任务不存在或不是每日任务");
        }

        // 计算奖励
        int baseReward = checkinTask.getReward();
        int consecutiveDays = (Integer) checkinInfo.get("consecutive_days");
        int bonusReward = 0;
        if (consecutiveDays >= 7) {
            bonusReward = baseReward; // 连续7天额外奖励
        }
        int totalReward = baseReward + bonusReward;

        // 记录签到
        UserTask userTask = new UserTask();
        userTask.setUserId(userId);
        userTask.setTaskId(checkinTask.getId());
        userTask.setProgress(1);
        userTask.setTarget(totalReward); // 使用target存储实际获得的奖励
        userTask.setIsCompleted(true);
        userTask.setCompletedAt(LocalDateTime.now());
        userTask.setIsClaimed(true);
        userTask.setClaimedAt(LocalDateTime.now());
        userTask.setDate(LocalDate.now());
        userTask.setCreatedAt(LocalDateTime.now());
        userTask.setUpdatedAt(LocalDateTime.now());
        boolean saved = userTaskMapper.insert(userTask) > 0;

        Map<String, Object> result = new HashMap<>();
        
        if (saved) {
            // 发放奖励
            if (totalReward > 0) {
                coinService.addCoins(userId, totalReward, "task", 
                    "每日签到奖励", "完成每日签到任务", checkinTask.getId(), "task");
            }
            // 检查签到成就
            achievementService.checkCheckinAchievements(userId);
        } else {
            result.put("success", false);
            result.put("message", "签到失败");
        }
        
        return result;
    }

    @Override
    @Transactional
    public boolean completeTask(Long userId, Long taskId) {
        Task task = getById(taskId);
        if (task == null || task.getStatus() != 1) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "任务不存在或已失效");
        }

        // 检查用户是否已完成该任务
        LambdaQueryWrapper<UserTask> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserTask::getUserId, userId)
                .eq(UserTask::getTaskId, taskId);
        if ("daily".equals(task.getType())) {
            queryWrapper.eq(UserTask::getDate, LocalDate.now()); // 每日任务检查今日是否完成
        }
        UserTask existingUserTask = userTaskMapper.selectOne(queryWrapper);

        if (existingUserTask != null) {
            // 检查任务是否已完成
            if (existingUserTask.getIsCompleted()) {
                throw new BizException(ErrorCode.OPERATION_ERROR, "任务已完成，请勿重复提交");
            }
            
            // 检查今日完成次数是否已达到目标
            Integer currentProgress = existingUserTask.getProgress() != null ? existingUserTask.getProgress() : 0;
            Integer targetProgress = task.getTarget() != null ? task.getTarget() : 1;
            
            if (currentProgress >= targetProgress) {
                throw new BizException(ErrorCode.OPERATION_ERROR, 
                    "今日完成次数已达上限(" + targetProgress + "次)，请明日再试");
            }
        }

        // 记录任务完成
        UserTask userTask;
        Integer targetProgress = task.getTarget() != null ? task.getTarget() : 1;
        boolean shouldGiveReward = false;
        boolean saved = false;
        
        if (existingUserTask != null) {
            // 更新现有记录
            userTask = existingUserTask;
            Integer currentProgress = userTask.getProgress() != null ? userTask.getProgress() : 0;
            Integer newProgress = currentProgress + 1;
            
            userTask.setProgress(newProgress);
            
            // 检查是否达到目标
            if (newProgress >= targetProgress) {
                userTask.setIsCompleted(true);
                userTask.setCompletedAt(LocalDateTime.now());
                userTask.setIsClaimed(true);
                userTask.setClaimedAt(LocalDateTime.now());
                shouldGiveReward = true;
            }
            
            saved = userTaskMapper.updateById(userTask) > 0;
        } else {
            // 创建新记录
            userTask = new UserTask();
            userTask.setUserId(userId);
            userTask.setTaskId(taskId);
            userTask.setProgress(1);
            userTask.setTarget(targetProgress);
            userTask.setDate(LocalDate.now());
            userTask.setCreatedAt(LocalDateTime.now());
            userTask.setUpdatedAt(LocalDateTime.now());
            
            // 如果目标就是1，直接完成
            if (targetProgress <= 1) {
                userTask.setIsCompleted(true);
                userTask.setCompletedAt(LocalDateTime.now());
                userTask.setIsClaimed(true);
                userTask.setClaimedAt(LocalDateTime.now());
                shouldGiveReward = true;
            }
            
            saved = userTaskMapper.insert(userTask) > 0;
        }

        if (saved) {
            // 只有在任务真正完成时才发放奖励
            if (shouldGiveReward && task.getReward() != null && task.getReward() > 0) {
                coinService.addCoins(userId, task.getReward(), "task", 
                    "完成任务奖励: " + task.getTitle(), "完成任务: " + task.getTitle(), task.getId(), "task");
            }
            // 如果完成的是每日任务，检查相关成就
            if (shouldGiveReward && "daily".equals(task.getType())) {
                achievementService.checkTaskCompletionAchievements(userId);
            }
            // TODO: 如果奖励是道具，需要调用道具服务
        }
        return saved;
    }

    @Override
    public List<TaskDTO> getAchievements(Long userId) {
        LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Task::getType, "achievement")
                .eq(Task::getStatus, 1)
                .orderByAsc(Task::getSortOrder);
        List<Task> achievements = list(queryWrapper);

        return achievements.stream()
                .map(task -> convertToTaskDTO(task, userId))
                .collect(Collectors.toList());
    }



    @Override
    @Transactional
    public boolean watchAdvertisement(Long userId) {
        // 查找观看广告任务配置
        LambdaQueryWrapper<Task> taskQuery = new LambdaQueryWrapper<>();
        taskQuery.eq(Task::getTaskKey, "daily_watch_ad")
                .eq(Task::getStatus, 1);
        Task adTask = getOne(taskQuery);
        
        if (adTask == null || !"daily".equals(adTask.getType())) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "观看广告任务不存在或已失效");
        }

        // 检查今日是否已完成观看广告任务
        LambdaQueryWrapper<UserTask> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserTask::getUserId, userId)
                .eq(UserTask::getTaskId, adTask.getId())
                .eq(UserTask::getDate, LocalDate.now());
        UserTask existingUserTask = userTaskMapper.selectOne(queryWrapper);

        if (existingUserTask != null && existingUserTask.getIsCompleted()) {
            throw new BizException(ErrorCode.OPERATION_ERROR, "今日已观看广告并领取奖励");
        }

        // 记录任务完成
        UserTask userTask = Optional.ofNullable(existingUserTask).orElse(new UserTask());
        userTask.setUserId(userId);
        userTask.setTaskId(adTask.getId());
        userTask.setProgress(adTask.getTarget());
        userTask.setTarget(adTask.getTarget());
        userTask.setIsCompleted(true);
        userTask.setCompletedAt(LocalDateTime.now());
        userTask.setIsClaimed(true);
        userTask.setClaimedAt(LocalDateTime.now());
        userTask.setDate(LocalDate.now());
        userTask.setUpdatedAt(LocalDateTime.now());
        userTask.setCreatedAt(userTask.getCreatedAt() == null ? LocalDateTime.now() : userTask.getCreatedAt());

        boolean saved;
        if (userTask.getId() == null) {
            saved = userTaskMapper.insert(userTask) > 0;
        } else {
            saved = userTaskMapper.updateById(userTask) > 0;
        }

        if (saved) {
            // 发放奖励
            if (adTask.getReward() != null && adTask.getReward() > 0) {
                coinService.addCoins(userId, adTask.getReward(), "task", 
                    "观看广告奖励", "观看广告完成", adTask.getId(), "task");
            }
            // TODO: 如果奖励是道具，需要调用道具服务
        }
        return saved;
    }

    @Override
    public Map<String, Object> getAdInfo() {
        Map<String, Object> adInfo = new HashMap<>();
        adInfo.put("adUrl", "https://example.com/ad_video.mp4");
        adInfo.put("rewardDescription", "观看完整广告可获得10爱心币");
        adInfo.put("durationSeconds", 30);
        return adInfo;
    }

    @Override
    public TaskDTO convertToTaskDTO(Task task, Long userId) {
        if (task == null) {
            return null;
        }
        TaskDTO dto = new TaskDTO();
        // 手动设置字段，处理类型转换
        dto.setId(task.getId());
        dto.setName(task.getTitle());
        dto.setDescription(task.getDescription());
        dto.setType(task.getType());
        // 将Integer类型的reward转换为BigDecimal
        if (task.getReward() != null) {
            dto.setRewardAmount(task.getReward());
        }
        dto.setRewardType("coin"); // 默认为爱心币奖励
        dto.setRewardItemId(null);

        // 获取用户任务状态
        LambdaQueryWrapper<UserTask> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserTask::getUserId, userId)
                .eq(UserTask::getTaskId, task.getId());
        if ("daily".equals(task.getType())) {
            queryWrapper.eq(UserTask::getDate, LocalDate.now()); // 每日任务只看今日完成情况
        }
        UserTask userTask = userTaskMapper.selectOne(queryWrapper);

        if (userTask != null) {
            if (userTask.getIsClaimed()) {
                dto.setUserTaskStatus("claimed");
            } else if (userTask.getIsCompleted()) {
                dto.setUserTaskStatus("completed");
            } else {
                dto.setUserTaskStatus("in_progress");
            }
            dto.setHasClaimed(userTask.getIsClaimed());
        } else {
            dto.setUserTaskStatus("pending");
            dto.setHasClaimed(false);
        }

        return dto;
    }

    @Override
    public List<TaskDTO> getVipTasks(Long userId) {
        // 1. 检查用户是否VIP
        User user = userMapper.selectById(userId);
        boolean isVip = user != null && user.getIsVip() != null && user.getIsVip();
        
        if (!isVip) {
            // 非VIP用户返回空列表
            return new ArrayList<>();
        }
        
        // 2. 查询VIP专属任务
        LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Task::getType, "vip")
               .eq(Task::getStatus, 1) // 状态正常
               .orderByAsc(Task::getSortOrder);
        List<Task> vipTasks = taskMapper.selectList(wrapper);
        
        // 3. 转换为DTO并添加用户完成状态
        return vipTasks.stream()
                .map(task -> convertToTaskDTO(task, userId))
                .collect(Collectors.toList());
    }
}